Load libraries
library(dplyr)
library(readr)
library(rgdal)
library(spdep)
library(tidyr)
library(ggplot2)
library(geofacet)
library(viridis)
library(plotly)
Read in required files
bairro_shp <- readOGR("Shapefiles/Bairro/", "Bairros_from_CTs")
OGR data source with driver: ESRI Shapefile
Source: "/Users/Sudipta/Documents/Harvard - SM80/Thesis/Fortaleza_Hom_RGit/Shapefiles/Bairro", layer: "Bairros_from_CTs"
with 119 features
It has 4 fields
Get median age at various levels of stratification (bairro, year, and bairro-year)
#Get overall median age
median_age_all <- median(homs$Age, na.rm = TRUE)
#Create dataframes of median by different strata
age_by_yr_bairro <- homs %>% dplyr::select(Age, Bairro, YOD) %>% group_by(Bairro, YOD) %>% summarize(median_age = median(Age, na.rm=TRUE), count = n(), mean_age = mean(Age, na.rm=TRUE))
age_by_bairro <- homs %>% dplyr::select(Age, Bairro, YOD) %>% group_by(Bairro) %>% summarize(median_age = median(Age, na.rm=TRUE), count = n(), mean_age = mean(Age, na.rm=TRUE))
age_by_yr <- homs %>% dplyr::select(Age, Bairro, YOD) %>% group_by(YOD) %>% summarize(median_age = median(Age, na.rm=TRUE), count = n(), mean_age = mean(Age, na.rm=TRUE))
Now plotting yearly median age and count on the same plot
ggplot(age_by_yr, aes(x=YOD)) + geom_line(aes(y=median_age, colour="Median Age")) + geom_line(aes(y=log(count)*3.9, colour="Count")) + #transform to get on same axis
scale_y_continuous(sec.axis = sec_axis(~exp(./3.9), name="Count")) + scale_colour_manual(values = c("blue", "red")) + labs(y = "Median Age", x = "Year")

Plot the median age by bairro on a map
bairro_shp@data <- cbind(bairro_shp@data, trueCentroids@coords)
bairro_ggplot <- shape_to_ggplot(bairro_shp)
Regions defined for each Polygons
column name ‘id’ is duplicated in the result
ggplot() + geom_polygon(data = bairro_ggplot, aes(x = long, y = lat, group = group, fill=median_age), size=0.1, color="black",) +
scale_fill_viridis(trans="reverse") + geom_point(data = bairro_ggplot, aes(x=x,y=y, color=log(count)*4), size=1.5) + scale_color_viridis(option = "magma") +
theme(line = element_blank(),
plot.title = element_text(hjust = 0.5),
axis.text=element_blank(),
axis.title=element_blank(),
legend.text=element_text(size=8),
legend.title=element_text(size=8),
panel.background = element_blank()) + coord_equal()

ggplot() + geom_polygon(data = bairro_ggplot, aes(x = long, y = lat, group = group, fill=log(count)*4), size=0.1, color="black") +
scale_fill_viridis() +
theme(line = element_blank(),
plot.title = element_text(hjust = 0.5),
axis.text=element_blank(),
axis.title=element_blank(),
legend.text=element_text(size=8),
legend.title=element_text(size=8),
panel.background = element_blank()) + coord_equal()

Get deviation for overall median age for all bairros by year
age_by_yr$dev <- age_by_yr$median_age - median_age_all
age_by_yr_bairro$dev <- age_by_yr_bairro$median_age - median_age_all
age_by_bairro$dev <- age_by_bairro$median_age - median_age_all
mygrid <- data.frame(
name = c("JACARECANGA", "PIRAMBU", "CRISTO REDENTOR", "BARRA DO CEARA", "CAIS DO PORTO", "MEIRELES", "PRAIA DE IRACEMA", "MOURA BRASIL", "VILA VELHA", "JARDIM IRACEMA", "FLORESTA", "ALVARO WEYNE", "CARLITO PAMPLONA", "VARJOTA", "VICENTE PINZON", "MUCURIPE", "ALDEOTA", "CENTRO", "FARIAS BRITO", "QUINTINO CUNHA", "MONTE CASTELO", "VILA ELLERY", "JARDIM GUANABARA", "PRESIDENTE KENNEDY", "OLAVO OLIVEIRA", "SAO GERARDO/ALAGADICO", "DE LOURDES", "PRAIA DO FUTURO I", "GUARARAPES", "COCO", "ANTONIO BEZERRA", "PADRE ANDRADE", "PARQUE ARAXA", "BENFICA", "JOSE BONIFACIO", "JOAQUIM TAVORA", "DIONISIO TORRES", "RODOLFO TEOFILO", "GENIBAU", "JARDIM AMERICA", "LUCIANO CAVALCANTE", "MANUEL DIAS BRANCO", "PRAIA DO FUTURO II", "CIDADE 2000", "SALINAS", "SAO JOAO DO TAUAPE", "FATIMA", "AMADEU FURTADO", "PARQUELANDIA", "PICI", "PAPICU", "CONJUNTO CEARA I", "JARDIM DAS OLIVEIRAS", "AEROLANDIA", "PARQUE MANIBURA", "SAPIRANGA COITE", "EDSON QUEIROZ", "SABIAGUABA", "DOM LUSTOSA", "AUTRAN NUNES", "BELA VISTA", "CIDADE DOS FUNCIONARIOS", "ALTO DA BALANCA", "PARREAO", "BOM FUTURO", "DAMAS", "CONJUNTO CEARA II", "GRANJA LISBOA", "JOAO XXIII", "DIAS MACEDO", "CAJAZEIRAS", "VILA UNIAO", "COUTO FERNANDES", "PAN AMERICANO", "CAMBEBA", "JOSE DE ALENCAR", "CURIO", "LAGOA REDONDA", "HENRIQUE JORGE", "MONTESE", "AEROPORTO", "GRANJA PORTUGAL", "MONDUBIM", "CANINDEZINHO", "PARQUE DOIS IRMAOS", "PASSARE", "PARQUE IRACEMA", "BARROSO", "GUAJERU", "MESSEJANA", "COACU", "PARQUE SAO JOSE", "BOA VISTA", "ITAPERI", "BOM SUCESSO", "SERRINHA", "BOM JARDIM", "SIQUEIRA", "DEMOCRITO ROCHA", "VILA PERY", "JOCKEY CLUBE", "CONJUNTO ESPERANCA", "JANGURUSSU", "ANCURI", "SAO BENTO", "DENDE", "ITAOCA", "JARDIM CEARENSE", "PARANGABA", "PLANALTO AYRTON SENNA", "PARQUE PRESIDENTE VARGAS", "PAUPINA", "PARQUE SANTA ROSA", "MARAPONGA", "PALMEIRAS", "PARQUE SANTA MARIA", "MANOEL SATIRO", "PREFEITO JOSE WALTER", "PEDRAS"), code=c(1:119),
row = c(1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 10, 10, 10, 10, 10, 10, 10, 11, 11),
col = c(10, 9, 8, 7, 16, 13, 12, 11, 6, 7, 8, 9, 10, 15, 16, 14, 13, 12, 11, 6, 10, 9, 7, 8, 7, 8, 16, 17, 14, 15, 5, 6, 9, 10, 11, 12, 13, 9, 5, 10, 14, 17, 18, 15, 13, 12, 11, 8, 7, 6, 16, 4, 14, 12, 15, 16, 17, 18, 6, 5, 7, 13, 11, 10, 9, 8, 4, 3, 6, 12, 13, 10, 8, 7, 14, 16, 15, 17, 5, 9, 11, 4, 3, 2, 8, 9, 12, 13, 15, 14, 16, 6, 10, 7, 5, 11, 4, 3, 6, 9, 5, 11, 13, 14, 15, 8, 10, 12, 7, 4, 7, 13, 8, 11, 12, 9, 10, 11, 12),
stringsAsFactors = FALSE
)
geofacet::grid_preview(mygrid)
Note: You provided a user-specified grid. If this is a
generally-useful grid, please consider submitting it to become a
part of the geofacet package. You can do this easily by calling:
grid_submit(__grid_df_name__)

age_by_yr_bairro$colour <- ifelse(age_by_yr_bairro$dev < 0, "negative","positive")
age_by_yr_bairro <- age_by_yr_bairro[complete.cases(age_by_yr_bairro),]
ggplot(age_by_yr_bairro) + geom_col(aes(YOD, dev, fill=colour)) +
scale_fill_manual(values=c(negative="firebrick1",positive="steelblue")) + facet_geo(~Bairro,grid=mygrid, label="name") + theme_void() + theme(strip.background = element_blank(), strip.text.x = element_text(size=4))
Note: You provided a user-specified grid. If this is a generally-useful grid, please consider submitting it to become a
part of the geofacet package. You can do this easily by calling: grid_submit(__grid_df_name__)

age_by_bairro$colour <- ifelse(age_by_bairro$dev < 0, "negative","positive")
age_by_bairro <- age_by_bairro[complete.cases(age_by_bairro),]
ggplot(age_by_bairro) + geom_col(aes(x=0,y=dev, fill=colour)) +
scale_fill_manual(values=c(negative="firebrick1",positive="steelblue")) +
facet_geo(~ Bairro, grid = mygrid, label="name") + theme_void() + theme(strip.background = element_blank(), strip.text.x = element_text(size=2))
Note: You provided a user-specified grid. If this is a generally-useful grid, please consider submitting it to become a
part of the geofacet package. You can do this easily by calling: grid_submit(__grid_df_name__)

Some scatter plots to explore as well
ggplot(age_by_bairro, aes(x=log(count), y=median_age)) + geom_point() + geom_smooth(method="loess")

p <- ggplot(age_by_yr_bairro, aes(x=log(count), y=median_age)) + geom_point() + geom_smooth(method = "loess")
p

ggplotly(p)
We recommend that you use the dev version of ggplot2 with `ggplotly()`
Install it with: `devtools::install_github('hadley/ggplot2')`
LS0tCnRpdGxlOiAiRXhwbG9yaW5nIEFnZSBEaXN0cmlidXRpb25zIgpvdXRwdXQ6IGh0bWxfbm90ZWJvb2sKLS0tCgpMb2FkIGxpYnJhcmllcwoKYGBge3IgbWVzc2FnZT1GQUxTRX0KbGlicmFyeShkcGx5cikKbGlicmFyeShyZWFkcikKbGlicmFyeShyZ2RhbCkKbGlicmFyeShzcGRlcCkKbGlicmFyeSh0aWR5cikKbGlicmFyeShnZ3Bsb3QyKQpsaWJyYXJ5KGdlb2ZhY2V0KQpsaWJyYXJ5KHZpcmlkaXMpCmxpYnJhcnkocGxvdGx5KQpgYGAKClJlYWQgaW4gcmVxdWlyZWQgZmlsZXMKCmBgYHtyfQpob21zIDwtIHJlYWRfY3N2KCJ+L0RvY3VtZW50cy9IYXJ2YXJkIC0gU004MC9UaGVzaXMvRm9ydGFsZXphX0hvbV9SR2l0X1BSSVZBVEVfRmlsZXMvaG9tc193dGhfYmFpcnJvX0NUX2RmLmNzdiIsCmNvbF90eXBlcyA9IGNvbHMoQ0RfR0VPQ09EQiA9IGNvbF9jaGFyYWN0ZXIoKSwKQ0RfR0VPQ09ERCA9IGNvbF9jaGFyYWN0ZXIoKSwgQ0RfR0VPQ09ESSA9IGNvbF9jaGFyYWN0ZXIoKSwKQ0RfR0VPQ09ETSA9IGNvbF9jaGFyYWN0ZXIoKSwgQ0RfR0VPQ09EUyA9IGNvbF9jaGFyYWN0ZXIoKSwKRE9CID0gY29sX2RhdGUoZm9ybWF0ID0gIiVZLSVtLSVkIiksCkRPRCA9IGNvbF9kYXRlKGZvcm1hdCA9ICIlWS0lbS0lZCIpLApYMSA9IGNvbF9za2lwKCkpKQoKYmFpcnJvX3NocCA8LSByZWFkT0dSKCJTaGFwZWZpbGVzL0JhaXJyby8iLCAiQmFpcnJvc19mcm9tX0NUcyIpCmBgYAoKR2V0IG1lZGlhbiBhZ2UgYXQgdmFyaW91cyBsZXZlbHMgb2Ygc3RyYXRpZmljYXRpb24gKGJhaXJybywgeWVhciwgYW5kIGJhaXJyby15ZWFyKQpgYGB7cn0KI0dldCBvdmVyYWxsIG1lZGlhbiBhZ2UKbWVkaWFuX2FnZV9hbGwgPC0gbWVkaWFuKGhvbXMkQWdlLCBuYS5ybSA9IFRSVUUpCgojQ3JlYXRlIGRhdGFmcmFtZXMgb2YgbWVkaWFuIGJ5IGRpZmZlcmVudCBzdHJhdGEKYWdlX2J5X3lyX2JhaXJybyA8LSBob21zICU+JSBkcGx5cjo6c2VsZWN0KEFnZSwgQmFpcnJvLCBZT0QpICU+JSBncm91cF9ieShCYWlycm8sIFlPRCkgJT4lIHN1bW1hcml6ZShtZWRpYW5fYWdlID0gbWVkaWFuKEFnZSwgbmEucm09VFJVRSksIGNvdW50ID0gbigpLCBtZWFuX2FnZSA9IG1lYW4oQWdlLCBuYS5ybT1UUlVFKSkKYWdlX2J5X2JhaXJybyA8LSBob21zICU+JSBkcGx5cjo6c2VsZWN0KEFnZSwgQmFpcnJvLCBZT0QpICU+JSBncm91cF9ieShCYWlycm8pICU+JSBzdW1tYXJpemUobWVkaWFuX2FnZSA9IG1lZGlhbihBZ2UsIG5hLnJtPVRSVUUpLCBjb3VudCA9IG4oKSwgbWVhbl9hZ2UgPSBtZWFuKEFnZSwgbmEucm09VFJVRSkpCmFnZV9ieV95ciA8LSBob21zICU+JSBkcGx5cjo6c2VsZWN0KEFnZSwgQmFpcnJvLCBZT0QpICU+JSBncm91cF9ieShZT0QpICU+JSBzdW1tYXJpemUobWVkaWFuX2FnZSA9IG1lZGlhbihBZ2UsIG5hLnJtPVRSVUUpLCBjb3VudCA9IG4oKSwgbWVhbl9hZ2UgPSBtZWFuKEFnZSwgbmEucm09VFJVRSkpCmBgYAoKCk5vdyBwbG90dGluZyB5ZWFybHkgbWVkaWFuIGFnZSBhbmQgY291bnQgb24gdGhlIHNhbWUgcGxvdApgYGB7cn0KZ2dwbG90KGFnZV9ieV95ciwgYWVzKHg9WU9EKSkgKyBnZW9tX2xpbmUoYWVzKHk9bWVkaWFuX2FnZSwgY29sb3VyPSJNZWRpYW4gQWdlIikpICsgZ2VvbV9saW5lKGFlcyh5PWxvZyhjb3VudCkqMy45LCBjb2xvdXI9IkNvdW50IikpICsgI3RyYW5zZm9ybSB0byBnZXQgb24gc2FtZSBheGlzCnNjYWxlX3lfY29udGludW91cyhzZWMuYXhpcyA9IHNlY19heGlzKH5leHAoLi8zLjkpLCBuYW1lPSJDb3VudCIpKSArICBzY2FsZV9jb2xvdXJfbWFudWFsKHZhbHVlcyA9IGMoImJsdWUiLCAicmVkIikpICsgbGFicyh5ID0gIk1lZGlhbiBBZ2UiLCB4ID0gIlllYXIiKQpgYGAKClBsb3QgdGhlIG1lZGlhbiBhZ2UgYnkgYmFpcnJvIG9uIGEgbWFwCgpgYGB7cn0Kc291cmNlKCJBY2Nlc3NvcnlfZnVuY3Rpb25zLlIiKQpiYWlycm9fc2hwQGRhdGEgPC0gbGVmdF9qb2luKGJhaXJyb19zaHBAZGF0YSwgYWdlX2J5X2JhaXJybywgYnk9Yygibm9tZV9ub3ZvIj0iQmFpcnJvIikpCgp0cnVlQ2VudHJvaWRzID0gZ0NlbnRyb2lkKGJhaXJyb19zaHAsYnlpZD1UUlVFKQpiYWlycm9fc2hwQGRhdGEgPC0gY2JpbmQoYmFpcnJvX3NocEBkYXRhLCB0cnVlQ2VudHJvaWRzQGNvb3JkcykKCmJhaXJyb19nZ3Bsb3QgPC0gc2hhcGVfdG9fZ2dwbG90KGJhaXJyb19zaHApCmBgYAoKYGBge3J9CgpnZ3Bsb3QoKSArIGdlb21fcG9seWdvbihkYXRhID0gYmFpcnJvX2dncGxvdCwgYWVzKHggPSBsb25nLCB5ID0gbGF0LCBncm91cCA9IGdyb3VwLCBmaWxsPW1lZGlhbl9hZ2UpLCBzaXplPTAuMSwgY29sb3I9ImJsYWNrIiwpICsgICAgICAgIAogICAgc2NhbGVfZmlsbF92aXJpZGlzKHRyYW5zPSJyZXZlcnNlIikgKyBnZW9tX3BvaW50KGRhdGEgPSBiYWlycm9fZ2dwbG90LCBhZXMoeD14LHk9eSwgY29sb3I9bG9nKGNvdW50KSo0KSwgc2l6ZT0xLjUpICsgc2NhbGVfY29sb3JfdmlyaWRpcyhvcHRpb24gPSAibWFnbWEiKSArCiAgICB0aGVtZShsaW5lID0gZWxlbWVudF9ibGFuaygpLAogICAgICAgICAgcGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChoanVzdCA9IDAuNSksCiAgICAgICAgICBheGlzLnRleHQ9ZWxlbWVudF9ibGFuaygpLCAgIAogICAgICAgICAgYXhpcy50aXRsZT1lbGVtZW50X2JsYW5rKCksCiAgICAgICAgICBsZWdlbmQudGV4dD1lbGVtZW50X3RleHQoc2l6ZT04KSwKICAgICAgICAgIGxlZ2VuZC50aXRsZT1lbGVtZW50X3RleHQoc2l6ZT04KSwKICAgICAgICAgIHBhbmVsLmJhY2tncm91bmQgPSBlbGVtZW50X2JsYW5rKCkpICsgY29vcmRfZXF1YWwoKQoKZ2dwbG90KCkgKyBnZW9tX3BvbHlnb24oZGF0YSA9IGJhaXJyb19nZ3Bsb3QsIGFlcyh4ID0gbG9uZywgeSA9IGxhdCwgZ3JvdXAgPSBncm91cCwgZmlsbD1sb2coY291bnQpKjQpLCBzaXplPTAuMSwgY29sb3I9ImJsYWNrIikgKyAgICAgICAgIAogICAgc2NhbGVfZmlsbF92aXJpZGlzKCkgKwogICAgdGhlbWUobGluZSA9IGVsZW1lbnRfYmxhbmsoKSwKICAgICAgICAgIHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLjUpLAogICAgICAgICAgYXhpcy50ZXh0PWVsZW1lbnRfYmxhbmsoKSwgICAKICAgICAgICAgIGF4aXMudGl0bGU9ZWxlbWVudF9ibGFuaygpLAogICAgICAgICAgbGVnZW5kLnRleHQ9ZWxlbWVudF90ZXh0KHNpemU9OCksCiAgICAgICAgICBsZWdlbmQudGl0bGU9ZWxlbWVudF90ZXh0KHNpemU9OCksCiAgICAgICAgICBwYW5lbC5iYWNrZ3JvdW5kID0gZWxlbWVudF9ibGFuaygpKSArIGNvb3JkX2VxdWFsKCkKYGBgCgoKR2V0IGRldmlhdGlvbiBmb3Igb3ZlcmFsbCBtZWRpYW4gYWdlIGZvciBhbGwgYmFpcnJvcyBieSB5ZWFyCmBgYHtyfQphZ2VfYnlfeXIkZGV2IDwtIGFnZV9ieV95ciRtZWRpYW5fYWdlIC0gbWVkaWFuX2FnZV9hbGwKYWdlX2J5X3lyX2JhaXJybyRkZXYgPC0gYWdlX2J5X3lyX2JhaXJybyRtZWRpYW5fYWdlIC0gbWVkaWFuX2FnZV9hbGwKYWdlX2J5X2JhaXJybyRkZXYgPC0gYWdlX2J5X2JhaXJybyRtZWRpYW5fYWdlIC0gbWVkaWFuX2FnZV9hbGwKYGBgCgpgYGB7cn0KbXlncmlkIDwtIGRhdGEuZnJhbWUoCiAgbmFtZSA9IGMoIkpBQ0FSRUNBTkdBIiwgIlBJUkFNQlUiLCAiQ1JJU1RPIFJFREVOVE9SIiwgIkJBUlJBIERPIENFQVJBIiwgIkNBSVMgRE8gUE9SVE8iLCAiTUVJUkVMRVMiLCAiUFJBSUEgREUgSVJBQ0VNQSIsICJNT1VSQSBCUkFTSUwiLCAiVklMQSBWRUxIQSIsICJKQVJESU0gSVJBQ0VNQSIsICJGTE9SRVNUQSIsICJBTFZBUk8gV0VZTkUiLCAiQ0FSTElUTyBQQU1QTE9OQSIsICJWQVJKT1RBIiwgIlZJQ0VOVEUgUElOWk9OIiwgIk1VQ1VSSVBFIiwgIkFMREVPVEEiLCAiQ0VOVFJPIiwgIkZBUklBUyBCUklUTyIsICJRVUlOVElOTyBDVU5IQSIsICJNT05URSBDQVNURUxPIiwgIlZJTEEgRUxMRVJZIiwgIkpBUkRJTSBHVUFOQUJBUkEiLCAiUFJFU0lERU5URSBLRU5ORURZIiwgIk9MQVZPIE9MSVZFSVJBIiwgIlNBTyBHRVJBUkRPL0FMQUdBRElDTyIsICJERSBMT1VSREVTIiwgIlBSQUlBIERPIEZVVFVSTyBJIiwgIkdVQVJBUkFQRVMiLCAiQ09DTyIsICJBTlRPTklPIEJFWkVSUkEiLCAiUEFEUkUgQU5EUkFERSIsICJQQVJRVUUgQVJBWEEiLCAiQkVORklDQSIsICJKT1NFIEJPTklGQUNJTyIsICJKT0FRVUlNIFRBVk9SQSIsICJESU9OSVNJTyBUT1JSRVMiLCAiUk9ET0xGTyBURU9GSUxPIiwgIkdFTklCQVUiLCAiSkFSRElNIEFNRVJJQ0EiLCAiTFVDSUFOTyBDQVZBTENBTlRFIiwgIk1BTlVFTCBESUFTIEJSQU5DTyIsICJQUkFJQSBETyBGVVRVUk8gSUkiLCAiQ0lEQURFIDIwMDAiLCAiU0FMSU5BUyIsICJTQU8gSk9BTyBETyBUQVVBUEUiLCAiRkFUSU1BIiwgIkFNQURFVSBGVVJUQURPIiwgIlBBUlFVRUxBTkRJQSIsICJQSUNJIiwgIlBBUElDVSIsICJDT05KVU5UTyBDRUFSQSBJIiwgIkpBUkRJTSBEQVMgT0xJVkVJUkFTIiwgIkFFUk9MQU5ESUEiLCAiUEFSUVVFIE1BTklCVVJBIiwgIlNBUElSQU5HQSBDT0lURSIsICJFRFNPTiBRVUVJUk9aIiwgIlNBQklBR1VBQkEiLCAiRE9NIExVU1RPU0EiLCAiQVVUUkFOIE5VTkVTIiwgIkJFTEEgVklTVEEiLCAiQ0lEQURFIERPUyBGVU5DSU9OQVJJT1MiLCAiQUxUTyBEQSBCQUxBTkNBIiwgIlBBUlJFQU8iLCAiQk9NIEZVVFVSTyIsICJEQU1BUyIsICJDT05KVU5UTyBDRUFSQSBJSSIsICJHUkFOSkEgTElTQk9BIiwgIkpPQU8gWFhJSUkiLCAiRElBUyBNQUNFRE8iLCAiQ0FKQVpFSVJBUyIsICJWSUxBIFVOSUFPIiwgIkNPVVRPIEZFUk5BTkRFUyIsICJQQU4gQU1FUklDQU5PIiwgIkNBTUJFQkEiLCAiSk9TRSBERSBBTEVOQ0FSIiwgIkNVUklPIiwgIkxBR09BIFJFRE9OREEiLCAiSEVOUklRVUUgSk9SR0UiLCAiTU9OVEVTRSIsICJBRVJPUE9SVE8iLCAiR1JBTkpBIFBPUlRVR0FMIiwgIk1PTkRVQklNIiwgIkNBTklOREVaSU5ITyIsICJQQVJRVUUgRE9JUyBJUk1BT1MiLCAiUEFTU0FSRSIsICJQQVJRVUUgSVJBQ0VNQSIsICJCQVJST1NPIiwgIkdVQUpFUlUiLCAiTUVTU0VKQU5BIiwgIkNPQUNVIiwgIlBBUlFVRSBTQU8gSk9TRSIsICJCT0EgVklTVEEiLCAiSVRBUEVSSSIsICJCT00gU1VDRVNTTyIsICJTRVJSSU5IQSIsICJCT00gSkFSRElNIiwgIlNJUVVFSVJBIiwgIkRFTU9DUklUTyBST0NIQSIsICJWSUxBIFBFUlkiLCAiSk9DS0VZIENMVUJFIiwgIkNPTkpVTlRPIEVTUEVSQU5DQSIsICJKQU5HVVJVU1NVIiwgIkFOQ1VSSSIsICJTQU8gQkVOVE8iLCAiREVOREUiLCAiSVRBT0NBIiwgIkpBUkRJTSBDRUFSRU5TRSIsICJQQVJBTkdBQkEiLCAiUExBTkFMVE8gQVlSVE9OIFNFTk5BIiwgIlBBUlFVRSBQUkVTSURFTlRFIFZBUkdBUyIsICJQQVVQSU5BIiwgIlBBUlFVRSBTQU5UQSBST1NBIiwgIk1BUkFQT05HQSIsICJQQUxNRUlSQVMiLCAiUEFSUVVFIFNBTlRBIE1BUklBIiwgIk1BTk9FTCBTQVRJUk8iLCAiUFJFRkVJVE8gSk9TRSBXQUxURVIiLCAiUEVEUkFTIiksIGNvZGU9YygxOjExOSksCiAgcm93ID0gYygxLCAxLCAxLCAxLCAyLCAyLCAyLCAyLCAyLCAyLCAyLCAyLCAyLCAzLCAzLCAzLCAzLCAzLCAzLCAzLCAzLCAzLCAzLCAzLCA0LCA0LCA0LCA0LCA0LCA0LCA0LCA0LCA0LCA0LCA0LCA0LCA0LCA1LCA1LCA1LCA1LCA1LCA1LCA1LCA1LCA1LCA1LCA1LCA1LCA1LCA1LCA1LCA2LCA2LCA2LCA2LCA2LCA2LCA2LCA2LCA2LCA2LCA2LCA2LCA2LCA2LCA2LCA2LCA3LCA3LCA3LCA3LCA3LCA3LCA3LCA3LCA3LCA3LCA3LCA3LCA3LCA3LCA3LCA3LCA4LCA4LCA4LCA4LCA4LCA4LCA4LCA4LCA4LCA4LCA4LCA4LCA4LCA4LCA5LCA5LCA5LCA5LCA5LCA5LCA5LCA5LCA5LCA5LCA5LCA5LCAxMCwgMTAsIDEwLCAxMCwgMTAsIDEwLCAxMCwgMTEsIDExKSwKICBjb2wgPSBjKDEwLCA5LCA4LCA3LCAxNiwgMTMsIDEyLCAxMSwgNiwgNywgOCwgOSwgMTAsIDE1LCAxNiwgMTQsIDEzLCAxMiwgMTEsIDYsIDEwLCA5LCA3LCA4LCA3LCA4LCAxNiwgMTcsIDE0LCAxNSwgNSwgNiwgOSwgMTAsIDExLCAxMiwgMTMsIDksIDUsIDEwLCAxNCwgMTcsIDE4LCAxNSwgMTMsIDEyLCAxMSwgOCwgNywgNiwgMTYsIDQsIDE0LCAxMiwgMTUsIDE2LCAxNywgMTgsIDYsIDUsIDcsIDEzLCAxMSwgMTAsIDksIDgsIDQsIDMsIDYsIDEyLCAxMywgMTAsIDgsIDcsIDE0LCAxNiwgMTUsIDE3LCA1LCA5LCAxMSwgNCwgMywgMiwgOCwgOSwgMTIsIDEzLCAxNSwgMTQsIDE2LCA2LCAxMCwgNywgNSwgMTEsIDQsIDMsIDYsIDksIDUsIDExLCAxMywgMTQsIDE1LCA4LCAxMCwgMTIsIDcsIDQsIDcsIDEzLCA4LCAxMSwgMTIsIDksIDEwLCAxMSwgMTIpLAogIHN0cmluZ3NBc0ZhY3RvcnMgPSBGQUxTRQopCmdlb2ZhY2V0OjpncmlkX3ByZXZpZXcobXlncmlkKQpgYGAKCmBgYHtyIGZpZy5oZWlnaHQ9MTAsIGZpZy53aWR0aD0xN30KYWdlX2J5X3lyX2JhaXJybyRjb2xvdXIgPC0gaWZlbHNlKGFnZV9ieV95cl9iYWlycm8kZGV2IDwgMCwgIm5lZ2F0aXZlIiwicG9zaXRpdmUiKQphZ2VfYnlfeXJfYmFpcnJvIDwtIGFnZV9ieV95cl9iYWlycm9bY29tcGxldGUuY2FzZXMoYWdlX2J5X3lyX2JhaXJybyksXQpnZ3Bsb3QoYWdlX2J5X3lyX2JhaXJybykgKyBnZW9tX2NvbChhZXMoWU9ELCBkZXYsIGZpbGw9Y29sb3VyKSkgKyAKICBzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXM9YyhuZWdhdGl2ZT0iZmlyZWJyaWNrMSIscG9zaXRpdmU9InN0ZWVsYmx1ZSIpKSArIGZhY2V0X2dlbyh+QmFpcnJvLGdyaWQ9bXlncmlkLCBsYWJlbD0ibmFtZSIpICsgdGhlbWVfdm9pZCgpICsgdGhlbWUoc3RyaXAuYmFja2dyb3VuZCA9IGVsZW1lbnRfYmxhbmsoKSwgc3RyaXAudGV4dC54ID0gZWxlbWVudF90ZXh0KHNpemU9NCkpCmBgYAoKCmBgYHtyfQphZ2VfYnlfYmFpcnJvJGNvbG91ciA8LSBpZmVsc2UoYWdlX2J5X2JhaXJybyRkZXYgPCAwLCAibmVnYXRpdmUiLCJwb3NpdGl2ZSIpCmFnZV9ieV9iYWlycm8gPC0gYWdlX2J5X2JhaXJyb1tjb21wbGV0ZS5jYXNlcyhhZ2VfYnlfYmFpcnJvKSxdCmdncGxvdChhZ2VfYnlfYmFpcnJvKSArIGdlb21fY29sKGFlcyh4PTAseT1kZXYsIGZpbGw9Y29sb3VyKSkgKwogIHNjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcz1jKG5lZ2F0aXZlPSJmaXJlYnJpY2sxIixwb3NpdGl2ZT0ic3RlZWxibHVlIikpICsKICBmYWNldF9nZW8ofiBCYWlycm8sIGdyaWQgPSBteWdyaWQsIGxhYmVsPSJuYW1lIikgKyB0aGVtZV92b2lkKCkgKyB0aGVtZShzdHJpcC5iYWNrZ3JvdW5kID0gZWxlbWVudF9ibGFuaygpLCBzdHJpcC50ZXh0LnggPSBlbGVtZW50X3RleHQoc2l6ZT0yKSkKYGBgCgpTb21lIHNjYXR0ZXIgcGxvdHMgdG8gZXhwbG9yZSBhcyB3ZWxsCmBgYHtyfQpnZ3Bsb3QoYWdlX2J5X2JhaXJybywgYWVzKHg9bG9nKGNvdW50KSwgeT1tZWRpYW5fYWdlKSkgKyBnZW9tX3BvaW50KCkgKyBnZW9tX3Ntb290aChtZXRob2Q9ImxvZXNzIikKcCA8LSBnZ3Bsb3QoYWdlX2J5X3lyX2JhaXJybywgYWVzKHg9bG9nKGNvdW50KSwgeT1tZWRpYW5fYWdlKSkgKyBnZW9tX3BvaW50KCkgKyBnZW9tX3Ntb290aChtZXRob2QgPSAibG9lc3MiKQpwCmdncGxvdGx5KHApCmBgYAoK